﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using UIObjects.TreeViewInterfaces;
using AbstraX.ClientInterfaces;
using System.Collections.ObjectModel;
using TreeBuilder.Contracts;
using MvvmTreeView;
using System.Windows.Controls;
using System.Windows;
using SL4PopupMenu;
using System.Diagnostics;

namespace TreeBuilder.ViewModels
{
    public class TreeBuilderTreeNodeRootSource : TreeBuilderTreeNodeBase
    {
        private ITreeNodeRootSource rootSource;
        private bool allowDrop;

        public TreeBuilderTreeNodeRootSource(ITreeBuilderService treeBuilderService, ITreeView treeView, ITreeNodeRootSource rootSource, ITreeNode parent) : base(treeBuilderService, treeView, parent)
        {
            this.rootSource = rootSource;
            this.Tag = rootSource;
            this.allowDrop = true;
        }

        public override ITreeNodeBase InternalNodeObject
        {
            get
            {
                return rootSource;
            }
        }

        public override AbstraX.ClientInterfaces.IBase BaseObject
        {
            get
            {
                return rootSource.BaseObject;
            }

            set
            {
                rootSource.BaseObject = value;
            }
        }

        public override void Expand()
        {
            if (!this.IsChildrenLoaded)
            {
                rootSource.ChildrenLoaded += new TreeBuilder.Contracts.ChildrenLoadedHandler(OnChildrenLoaded);
                rootSource.LoadChildren();
            }

            base.Expand();
        }

        public override string Text
        {
            get
            {
                return rootSource.Text;
            }

            set
            {
                rootSource.Text = value;
            }
        }

        private List<IContextMenuItem> GetSubMenus()
        {
            List<IContextMenuItem> subMenus = new List<IContextMenuItem>();

            if (rootSource.Source is IElement)
            {
                IElement element = (IElement)rootSource.Source;

                if (element.IsChildrenLoaded)
                {
                    if (element.Attributes != null)
                    {
                        foreach (var attribute in element.Attributes)
                        {
                            subMenus.Add(new ContextMenuItem(null, null, attribute.Name, attribute.Name, AddMemberAsNode));
                        }
                    }

                    foreach (var childElement in element.ChildElements)
                    {
                        subMenus.Add(new ContextMenuItem(null, null, childElement.Name, childElement.Name, AddMemberAsNode));
                    }
                }
                else
                {
                    element.ChildrenLoaded += parent =>
                    {
                        contextMenu = null;
                        treeView.ResetNodeMenu(this);
                    };

                    element.LoadChildren();
                }
            }

            return subMenus;
        }

        public void AddAsNode(object sender, RoutedEventArgs ea)
        {
            if (rootSource.Source is IElement)
            {
                var element = (IElement)rootSource.Source;
                var createOperation = treeBuilderService.CreateElementNode(rootSource, element);

                createOperation.NodeCreated += (parent, e) =>
                {
                    this.Nodes.Add(new TreeBuilderTreeNodeElementNode(treeBuilderService, treeView, createOperation.NewNode, this) { ChildOrdinal = this.Nodes.Count });
                    base.Expand();
                };
            }
            else if (rootSource.Source is IAttribute)
            {
                var attribute = (IAttribute)rootSource.Source;
                var createOperation = treeBuilderService.CreateAttributeNode(rootSource, attribute);

                createOperation.NodeCreated += (parent, e) =>
                {
                    this.Nodes.Add(new TreeBuilderTreeNodeAttributeNode(treeBuilderService, treeView, createOperation.NewNode, this) { ChildOrdinal = this.Nodes.Count });
                    base.Expand();
                };
            }
            else
            {
                Debugger.Break();
            }
        }

        public void AddFolder(object sender, RoutedEventArgs r)
        {
            var createOperation = treeBuilderService.CreateFolderNode(rootSource, rootSource.Source);

            createOperation.NodeCreated += (parent, e) =>
            {
                this.Nodes.Add(new TreeBuilderTreeNodeFolder(treeBuilderService, treeView, createOperation.NewNode, this) { ChildOrdinal = this.Nodes.Count });
                base.Expand();
            };
        }

        public void AddMemberAsNode(object sender, RoutedEventArgs r)
        {
            var rootElement = (IElement)rootSource.Source;
            var menu = (PopupMenuItem)sender;

            if (rootElement.Attributes != null && rootElement.Attributes.Any(a => a.Name == (string)menu.Tag))
            {
                var attribute = rootElement.Attributes.Single(a => a.Name == (string)menu.Tag);
                var createOperation = treeBuilderService.CreateAttributeNode(rootSource, attribute);

                createOperation.NodeCreated += (parent, e) =>
                {
                    this.Nodes.Add(new TreeBuilderTreeNodeAttributeNode(treeBuilderService, treeView, createOperation.NewNode, this) { ChildOrdinal = this.Nodes.Count });
                    base.Expand();
                };
            }
            else if (rootElement.ChildElements.Any(e => e.Name == (string)menu.Tag))
            {
                var element = rootElement.ChildElements.Single(a => a.Name == (string)menu.Tag);
                var createOperation = treeBuilderService.CreateElementNode(rootSource, element);

                createOperation.NodeCreated += (parent, e) =>
                {
                    this.Nodes.Add(new TreeBuilderTreeNodeElementNode(treeBuilderService, treeView, createOperation.NewNode, this) { ChildOrdinal = this.Nodes.Count });
                    base.Expand();
                };
            }
        }

        public override ContextMenu ContextMenu
        {
            get
            {
                if (contextMenu == null)
                {
                    contextMenu = new ContextMenu
                    {
                        Items = new List<IContextMenuItem>()
                        {
                            new ContextMenuItem(null, null, "Add as Node", null, AddAsNode),
                            new ContextMenuItem
                            {
                                Text = "Add Member as Node",
                                Items = GetSubMenus(),
                            },
                            new ContextMenuItem(null, null, "Add Folder", null, AddFolder),
                            new ContextMenuItem(null, null, "Add Query", null, AddQuery),
                            new ContextMenuItem(null, null, "Add Advanced Query...", null, AddAdvancedQuery),
                        }
                    };
                }

                return contextMenu;
            }

            set
            {
                contextMenu = value;
            }
        }

        public override bool? HasChildren
        {
            get { throw new NotImplementedException(); }
        }

        public override string ID
        {
            get 
            {
                return rootSource.ID;
            }
        }

        public override void LoadChildren()
        {
            rootSource.ChildrenLoaded += new TreeBuilder.Contracts.ChildrenLoadedHandler(OnChildrenLoaded);
            rootSource.LoadChildren();
        }

        public override IEnumerable<ITreeNodeBase> Children
        {
            get 
            {
                return rootSource.Children;
            }
        }

        public override void Remove()
        {
            rootSource.RemovedSuccessfully += (node, e) =>
            {
                this.parent.Nodes.Remove(this);

                var op = treeBuilderService.OrphansExist();

                op.Completed += (sender, e2) =>
                {
                    if (op.Value)
                    {
                        MessageBox.Show("Orphans exist!");
                    }
                };
            };

            rootSource.Remove();
        }

        public override bool AllowDrop
        {
            get
            {
                return allowDrop;
            }
            set
            {
                allowDrop = value;
            }
        }

        public override ITreeNode ShallowClone()
        {
            throw new NotImplementedException();
        }

		public override void OnSelect()
		{
		}
        public override ITreeNode DeepClone()
        {
            throw new NotImplementedException();
        }

        public override bool AllowRename
        {
            get
            {
                throw new NotImplementedException();
            }
            set
            {
                throw new NotImplementedException();
            }
        }

        public override bool HasLayoverImage<T>(out T image)
        {
            return rootSource.HasLayoverImage<T>(out image);
        }

        public override void AddNew(string shortCut)
        {
        }

        public override void DragEnter(object sender, UIObjects.DragDropInterfaces.DragEventArgs e)
        {
        }

        public override void DragLeave(object sender, UIObjects.DragDropInterfaces.DragEventArgs e)
        {
        }

        public override void DragOver(object sender, UIObjects.DragDropInterfaces.DragEventArgs e)
        {
        }

        public override void DragStarting(object sender, UIObjects.DragDropInterfaces.ItemDragEventArgs e)
        {
        }

        public override void DragCompleted(object sender, UIObjects.DragDropInterfaces.ItemDragEventArgs e)
        {
        }

        public override void ItemDropped(object sender, UIObjects.DragDropInterfaces.ItemDragEventArgs e, int insertionIndex)
        {
        }

        public override void GiveFeedback(object sender, UIObjects.DragDropInterfaces.GiveFeedbackEventArgs e)
        {
        }

        public override float ChildOrdinal
        {
            get
            {
                return rootSource.ChildOrdinal;
            }
            set
            {
                rootSource.ChildOrdinal = value;
            }
        }
    }
}
